/**
 * Arrays.java
 * @author: liuex
 * 2007-12-30 ����12:06:27
 *
 * note: 
 */
package org.lex.utils;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;

public class Arrays {
	public static <T> T[] combine(T[]... arrays) {
		// FIXME use System.arraycopy() to reimplement
		int len = 0;
		for (T[] array : arrays)
			len += array.length;
		ArrayList<T> list = new ArrayList<T>(len);
		for (T[] array : arrays)
			for (T e : array)
				list.add(e);
		return list.toArray(arrays[0]);
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] append(T[] a1, T... a2) {
		if (null == a1 && null == a2)
			throw new NullPointerException("����������ͬʱΪnull");
		if (null == a1 || null == a2)
			return null == a1 ? a2 : a1;
		if (0 == a1.length || 0 == a2.length)
			return 0 == a1.length ? a2 : a1;
		// ����a1��a2������null,���ҳ��ȶ�>=1
		T[] na = (T[]) Array.newInstance(a1.getClass().getComponentType(), a1.length + a2.length);
		System.arraycopy(a1, 0, na, 0, a1.length);
		System.arraycopy(a2, 0, na, a1.length, a2.length);
		return na;
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] insert(T[] a1, T... a2) {
		if (null == a1 && null == a2)
			throw new NullPointerException("����������ͬʱΪnull");
		if (null == a1 || null == a2)
			return null == a1 ? a2 : a1;
		if (0 == a1.length || 0 == a2.length)
			return 0 == a1.length ? a2 : a1;
		// ����a1��a2������null,���ҳ��ȶ�>=1
		T[] na = (T[]) Array.newInstance(a1.getClass().getComponentType(), a1.length + a2.length);
		System.arraycopy(a2, 0, na, 0, a2.length);
		System.arraycopy(a1, 0, na, a2.length, a1.length);
		return na;
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] removeReferences(T[] orig, T... references) {
		if (null == orig)
			throw new NullPointerException("orig array can't be null");
		if (0 == orig.length || null == references || 0 == references.length)
			return orig;
		// ����orig��references������null,���ҳ��ȶ�>=1
		ArrayList<T> list = new ArrayList<T>(orig.length);
		for (int i = 0; i < orig.length; i++)
			if (-1 == firstReference(references, orig[i]))
				list.add(orig[i]);
		return list.toArray((T[]) Array.newInstance(orig.getClass().getComponentType(), list.size()));
	}

	public static <T> T[] removeIndexes(T[] orig, int... indexes) {
		return null;
	}

	public static int[] removeIndexes(int[] orig, int... indexes) {
		if (0 == orig.length || null == indexes || 0 == indexes.length)
			return orig;
		// now orig != null, and indexes != null,and both longger than 1
		indexes = java.util.Arrays.copyOf(indexes, indexes.length);
		java.util.Arrays.sort(indexes);
		int index = 0;
		int[] copy = new int[orig.length - indexes.length];
		for (int i = 0; i < orig.length; i++) {
			if (java.util.Arrays.binarySearch(indexes, i) >= 0) {
				continue;
			} else {
				// if( index >= copy.length )
				// JOptionPane.showConfirmDialog( null, "Pause" );
				copy[index] = orig[i];
				index++;
			}
		}
		return copy;
	}

	/**
	 * ��������array�е�һ�γ��ֵ�e�����õ�����
	 * 
	 * @param array
	 * @param e
	 *            ��Ҫ���ҵ�����
	 * @return e�������е�������߲�����e������ʱ����-1
	 */
	public static <T> int firstReference(T[] array, T e) {
		if (null == array)
			return -1;
		for (int i = 0; i < array.length; i++)
			if (e == array[i])
				return i;
		return -1;
	}

	public static <T> int firstEquals(T[] array, T e) {
		if (null == array || null == e)
			throw new NullPointerException();
		for (int i = 0; i < array.length; i++)
			if (e.equals(array[i]))
				return i;
		return -1;
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] toArray(Iterator<T> i) {
		ArrayList<T> list = new ArrayList<T>();
		while (i.hasNext())
			list.add(i.next());
		return (T[]) list.toArray();
	}

	@SuppressWarnings("unchecked")
	public static <T> T[] toArray(Enumeration<T> e) {
		ArrayList<T> list = new ArrayList<T>();
		while (e.hasMoreElements())
			list.add(e.nextElement());
		return (T[]) list.toArray();
	}
}
